/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package edu.pku.sei.AMT.impl;

import edu.pku.sei.AMT.AmtPackage;
import edu.pku.sei.AMT.ModifierElement;
import edu.pku.sei.AMT.ObjectVariable;
import edu.pku.sei.AMT.Rule;
import edu.pku.sei.AMT.Section;
import edu.pku.sei.AMT.TypedModel;
import edu.pku.sei.AMT.Variable;

import java.util.Collection;

import org.eclipse.emf.common.notify.NotificationChain;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;

import org.eclipse.emf.ecore.util.EDataTypeUniqueEList;
import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Rule</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link edu.pku.sei.AMT.impl.RuleImpl#getModifiers <em>Modifiers</em>}</li>
 *   <li>{@link edu.pku.sei.AMT.impl.RuleImpl#getVariables <em>Variables</em>}</li>
 *   <li>{@link edu.pku.sei.AMT.impl.RuleImpl#getSections <em>Sections</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class RuleImpl extends NamedElementImpl implements Rule {
	/**
	 * The cached value of the '{@link #getModifiers() <em>Modifiers</em>}' attribute list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getModifiers()
	 * @generated
	 * @ordered
	 */
	protected EList modifiers;

	/**
	 * The cached value of the '{@link #getVariables() <em>Variables</em>}' containment reference list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getVariables()
	 * @generated
	 * @ordered
	 */
	protected EList variables;

	/**
	 * The cached value of the '{@link #getSections() <em>Sections</em>}' containment reference list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getSections()
	 * @generated
	 * @ordered
	 */
	protected EList sections;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected RuleImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected EClass eStaticClass() {
		return AmtPackage.Literals.RULE;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EList getModifiers() {
		if (modifiers == null) {
			modifiers = new EDataTypeUniqueEList(String.class, this, AmtPackage.RULE__MODIFIERS);
		}
		return modifiers;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EList getVariables() {
		if (variables == null) {
			variables = new EObjectContainmentEList(Variable.class, this, AmtPackage.RULE__VARIABLES);
		}
		return variables;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EList getSections() {
		if (sections == null) {
			sections = new EObjectContainmentEList(Section.class, this, AmtPackage.RULE__SECTIONS);
		}
		return sections;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public EList getSectionsByModifiers(EList modifiers) {
		EList result = new BasicEList();
		for(Object r : getSections()) {
			Section s = (Section)r;
			if(s.getModifiers().containsAll(modifiers))
				result.add(s);
		}
		return result;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case AmtPackage.RULE__VARIABLES:
				return ((InternalEList)getVariables()).basicRemove(otherEnd, msgs);
			case AmtPackage.RULE__SECTIONS:
				return ((InternalEList)getSections()).basicRemove(otherEnd, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case AmtPackage.RULE__MODIFIERS:
				return getModifiers();
			case AmtPackage.RULE__VARIABLES:
				return getVariables();
			case AmtPackage.RULE__SECTIONS:
				return getSections();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case AmtPackage.RULE__MODIFIERS:
				getModifiers().clear();
				getModifiers().addAll((Collection)newValue);
				return;
			case AmtPackage.RULE__VARIABLES:
				getVariables().clear();
				getVariables().addAll((Collection)newValue);
				return;
			case AmtPackage.RULE__SECTIONS:
				getSections().clear();
				getSections().addAll((Collection)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void eUnset(int featureID) {
		switch (featureID) {
			case AmtPackage.RULE__MODIFIERS:
				getModifiers().clear();
				return;
			case AmtPackage.RULE__VARIABLES:
				getVariables().clear();
				return;
			case AmtPackage.RULE__SECTIONS:
				getSections().clear();
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case AmtPackage.RULE__MODIFIERS:
				return modifiers != null && !modifiers.isEmpty();
			case AmtPackage.RULE__VARIABLES:
				return variables != null && !variables.isEmpty();
			case AmtPackage.RULE__SECTIONS:
				return sections != null && !sections.isEmpty();
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public int eBaseStructuralFeatureID(int derivedFeatureID, Class baseClass) {
		if (baseClass == ModifierElement.class) {
			switch (derivedFeatureID) {
				case AmtPackage.RULE__MODIFIERS: return AmtPackage.MODIFIER_ELEMENT__MODIFIERS;
				default: return -1;
			}
		}
		return super.eBaseStructuralFeatureID(derivedFeatureID, baseClass);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public int eDerivedStructuralFeatureID(int baseFeatureID, Class baseClass) {
		if (baseClass == ModifierElement.class) {
			switch (baseFeatureID) {
				case AmtPackage.MODIFIER_ELEMENT__MODIFIERS: return AmtPackage.RULE__MODIFIERS;
				default: return -1;
			}
		}
		return super.eDerivedStructuralFeatureID(baseFeatureID, baseClass);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (modifiers: ");
		result.append(modifiers);
		result.append(')');
		return result.toString();
	}

	/**
	 * @generated NOT
	 */
	public ObjectVariable getVariable(String name) {
		for(Object o : getVariables()) {
			ObjectVariable ov = (ObjectVariable)o;
			if(ov.getName().equals(name))
				return ov;
		}
		return null;
	}

	/**
	 * @generated NOT
	 */
	public EList getSectionsByModelName(String model) {
		EList result = new BasicEList();
		for(Object o : this.getSections() ) {
			Section t = (Section)o;
			
			if(model.equals(t.getModelName()))
				result.add(t);
		}
		
		return result;
	}

	/**
	 * @generated NOT
	 */
	public EList getExclusiveVariables(EList variables, EList exclusiveSections) {
		EList result = new BasicEList();
		for(Object vo : variables) {
			if(vo instanceof ObjectVariable)
				if(checkExclusive((ObjectVariable)vo, exclusiveSections))
					result.add(vo);
		}
		return result;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EList getSectionsByTypedModel(EList model) {
		EList<Section> result = new BasicEList<Section>();
		for(Object so : this.getSections()) {
			Section s = (Section)so;
			if(s.getModelName()!=null) {
				for(Object mo : model) {
					TypedModel m = (TypedModel)mo;
					if(m.getName().equals(s.getModelName()))
						result.add(s);
				}
			}
		}
		
		return result;
		
	}

	private boolean checkExclusive(ObjectVariable vo, EList exclusiveSections) {
		for(Object so : exclusiveSections) {
			Section s = (Section)so;
			if(s.getReferredVariables().contains(vo))
				return false;
		}
		return true;
	}

} //RuleImpl
